﻿// -----------------------------------------------------------------------
// <copyright file="Ticket.cs" company="Mar3ek">
//  http://mar3ek.wordpress.com
// </copyright>
// -----------------------------------------------------------------------

namespace LighthouseNET
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Xml.Linq;

    /// <summary>
    /// Class representing a Lighthouse ticket
    /// </summary>
    public class Ticket
    {
        #region Fields

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="Ticket"/> class. 
        /// </summary>
        /// <param name="title">
        /// The title.
        /// </param>
        /// <param name="body">
        /// The body.
        /// </param>
        /// <param name="state">
        /// The state.
        /// </param>
        /// <param name="assignedUserId">
        /// The assigned user id.
        /// </param>
        /// <param name="milestoneId">
        /// The milestone id.
        /// </param>
        /// <param name="tag">
        /// The tag.
        /// </param>
        public Ticket(
            string title,
            string body,
            string state,
            int assignedUserId,
            int milestoneId,
            string tag)
        {
            State = state;
            Title = title;
            RawBody = body;
            AssignedUserId = assignedUserId;
            MilestoneId = milestoneId;
            Tag = tag;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Ticket"/> class.
        /// </summary>
        /// <param name="assignedUserId">
        /// The assigned user id.
        /// </param>
        /// <param name="attachmentCount">
        /// The atatchment count.
        /// </param>
        /// <param name="rawBody">
        /// The raw body.
        /// </param>
        /// <param name="htmlBody">
        /// The html body.
        /// </param>
        /// <param name="createdAt">
        /// The created at.
        /// </param>
        /// <param name="creatorId">
        /// The creator id.
        /// </param>
        /// <param name="milestoneId">
        /// The milestone id.
        /// </param>
        /// <param name="number">
        /// The number.
        /// </param>
        /// <param name="permalink">
        /// The permalink.
        /// </param>
        /// <param name="projectId">
        /// The project id.
        /// </param>
        /// <param name="userId">
        /// The user Id.
        /// </param>
        /// <param name="state">
        /// The state.
        /// </param>
        /// <param name="title">
        /// The title.
        /// </param>
        /// <param name="updatedAt">
        /// The updated at.
        /// </param>
        /// <param name="tag">
        /// The tag.
        /// </param>
        /// <param name="versions">
        /// The versions.
        /// </param>
        private Ticket(
            string assignedUserId,
            int attachmentCount,
            string rawBody,
            string htmlBody,
            DateTime createdAt,
            int creatorId,
            int milestoneId,
            int number,
            string permalink,
            int projectId,
            int userId,
            string state,
            string title,
            DateTime updatedAt,
            string tag,
            IList<Ticket> versions)
        {
            AssignedUserId = string.IsNullOrEmpty(assignedUserId) ? 0 : int.Parse(assignedUserId);

            AttachmentsCount = attachmentCount;
            RawBody = rawBody;
            HtmlBody = htmlBody;
            CreatedAt = createdAt;
            CreatorId = creatorId;
            MilestoneId = milestoneId;
            Number = number;
            Permalink = permalink;
            ProjectId = projectId;
            State = state;
            Title = title;
            UpdatedAt = updatedAt;
            Tag = tag;
            UserId = userId;
            Versions = new ReadOnlyCollection<Ticket>(versions);
        }

        #region Properties

        /// <summary>
        /// Gets the assigned user's ID
        /// </summary>
        public int AssignedUserId { get; private set; }

        /// <summary>
        /// Gets the number of attachment
        /// </summary>
        public int AttachmentsCount { get; private set; }

        /// <summary>
        /// Gets the raw body
        /// </summary>
        public string RawBody { get; private set; }

        /// <summary>
        /// Gets the HTML body
        /// </summary>
        public string HtmlBody { get; private set; }

        /// <summary>
        /// Gets the time of creation
        /// </summary>
        public DateTime CreatedAt { get; private set; }

        /// <summary>
        /// Gets the creator's ID
        /// </summary>
        public int CreatorId { get; private set; }

        /// <summary>
        /// Gets the milestone ID
        /// </summary>
        public int MilestoneId { get; private set; }

        /// <summary>
        /// Gets the ticket number
        /// </summary>
        public int Number { get; private set; }

        /// <summary>
        /// Gets the ticket permalink
        /// </summary>
        public string Permalink { get; private set; }

        /// <summary>
        /// Gets the ticket state
        /// </summary>
        public string State { get; private set; }

        /// <summary>
        /// Gets the ticket title
        /// </summary>
        public string Title { get; private set; }

        /// <summary>
        /// Gets the last update time
        /// </summary>
        public DateTime UpdatedAt { get; private set; }

        /// <summary>
        /// Gets author's user ID
        /// </summary>
        public int UserId { get; private set; }

        /// <summary>
        /// Gets the ticket tags
        /// </summary>
        public string Tag { get; private set; }

        /// <summary>
        /// Gets the previous versions of the ticket
        /// </summary>
        public ReadOnlyCollection<Ticket> Versions { get; private set; }

        /// <summary>
        /// Gets the project ID
        /// </summary>
        public int ProjectId { get; private set; }

        #endregion

        /// <summary>
        /// Parses the specified element.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns>Parsed ticket</returns>
        /// <exception cref="ArgumentNullException">Element is null.</exception>
        internal static Ticket Parse(XElement element)
        {
            if (element == null || element.IsEmpty)
            {
                throw new ArgumentNullException("element");
            }

            // ReSharper disable PossibleNullReferenceException
            var assignedUserId = element.Element("assigned-user-id").Value;
            var attachmentCount = int.Parse(element.Element("attachments-count").Value);
            var body = element.Element("latest-body") != null ? element.Element("latest-body").Value : element.Element("body").Value;
            var bodyHtml = element.Element("original-body-html") != null ? element.Element("original-body-html").Value : element.Element("body-html").Value;
            var createdAt = Globals.DateTimeFromLighthouse(element.Element("created-at").Value);
            var creatorId = int.Parse(element.Element("creator-id").Value);
            int milestoneId;
            int.TryParse(element.Element("milestone-id").Value, out milestoneId);
            var number = int.Parse(element.Element("number").Value);
            var permalink = element.Element("permalink").Value;
            var projectId = int.Parse(element.Element("project-id").Value);
            var state = element.Element("state").Value;
            var title = element.Element("title").Value;
            var updatedAt = Globals.DateTimeFromLighthouse(element.Element("updated-at").Value);
            var userId = int.Parse(element.Element("user-id").Value);
            var tag = element.Element("tag").Value;
            var versions = element.Element("versions") != null ? element.Element("versions").Elements("version").Select(Parse).ToList() : new List<Ticket>();

            // ReSharper restore PossibleNullReferenceException
            return new Ticket(
                assignedUserId,
                attachmentCount,
                body,
                bodyHtml,
                createdAt,
                creatorId,
                milestoneId,
                number,
                permalink,
                projectId,
                userId,
                state,
                title,
                updatedAt,
                tag,
                versions);
        }
    }
}
